package gecko;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * {@link DevicePipeline} 是可以处理一类设备通讯协议的管理类。
 *
 * @author 陈永佳 (yoojiachen@gmail.com)
 * @version 0.0.1
 */
public abstract class DevicePipeline implements Bundle {

    private final Map<String, VirtualDevice> mAddressDevices = new HashMap<>();

    @Override
    public void onStart(GeckoScoped scoped) {
        forEach(dev -> scoped.detectTimeout("Device.启动",
                1000,
                () -> dev.onStart(scoped)));
    }

    @Override
    public void onStop(GeckoScoped scoped) {
        forEach(dev -> scoped.detectTimeout("Device.停止",
                1000,
                () -> dev.onStop(scoped)));

    }

    /**
     * 返回当前支持的通讯协议名称
     *
     * @return 协议名称
     */
    public abstract String getSupportProtocol();

    /**
     * 根据事件，返回指定设备地址的硬件对象。
     * 如果设备不存在，返回 null。
     *
     * @param deviceAddress 设备地址
     * @return 设备对象
     */
    public VirtualDevice findMatchedDevice(String deviceAddress) {
        return mAddressDevices.get(deviceAddress);
    }

    /**
     * 返回相同组地址的设备列表
     *
     * @param groupAddress 组地址
     * @return 设备列表
     */
    public Collection<VirtualDevice> getByGroupAddress(String groupAddress) {
        return mAddressDevices.values().stream()
                .filter(dev -> dev.getGroupAddress().equals(groupAddress))
                .collect(Collectors.toList());
    }

    /**
     * 获取当前设备列表。
     *
     * @return 设备对象列表
     */
    public final Collection<VirtualDevice> getDevices() {
        return mAddressDevices.values();
    }

    /**
     * 遍历设备列表
     *
     * @param consumer Consumer
     */
    public final void forEach(Consumer<VirtualDevice> consumer) {
        mAddressDevices.values().forEach(consumer);
    }

    /**
     * 添加设备对象。
     *
     * @param device 设备
     */
    final void addVirtualDevice(VirtualDevice device) {
        final String addr = device.getUnionAddress();
        if (mAddressDevices.containsKey(addr)) {
            throw new IllegalArgumentException("设备地址重复: " + addr);
        } else {
            mAddressDevices.put(addr, device);
        }
    }

    /**
     * 移除指定设备
     *
     * @param device 设备对象
     */
    void removeVirtualDevice(VirtualDevice device) {
        mAddressDevices.remove(device.getUnionAddress());
    }


}
